package com.dotflat.check.controller;

import com.dotflat.check.domain.CheckCard;
import com.dotflat.check.domain.Checker;
import com.dotflat.check.domain.RelId;
import com.dotflat.check.po.*;
import com.dotflat.check.service.CheckerService;
import com.dotflat.check.service.RelIdService;
import com.dotflat.check.service.TianBoCheckerService;
import com.dotflat.rest.controller.RestfulBaseController;
import com.dotflat.util.AccessControlUserIdUtil;
import com.dotflat.util.Base64ToFile;
import com.dotflat.util.excelUtil.StringUtils;
import com.matt.commons.dto.sso.AreaDTO;
import com.matt.commons.dto.sso.StaffDTO;
import com.matt.commons.model.StatusResponse;
import com.matt.commons.page.PagerQuery;
import com.matt.domain.Children;
import com.matt.domain.Classes;
import com.matt.domain.record.CheckRecord;
import com.matt.foundation.model.ErrorCode;
import com.matt.foundation.model.MemVerificationCache;
import com.matt.foundation.utils.CopyUtils;
import com.matt.foundation.utils.DateUtil;
import com.matt.service.ChildrenService;
import com.matt.service.ClassesService;
import com.matt.service.remoteCall.SsoCallService;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.annotations.Check;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.matt.foundation.constant.RequestConstant.TICKET;


/**
 * 巡检字典Controller
 *
 * @author #
 * @date 2021-11-25
 */
@RestController
@RequestMapping("/api/checker")
@Slf4j
@Api(tags = "考勤机 - 用户")
public class CheckerController extends RestfulBaseController<Checker, CheckerService, CheckerPO> {

    @Autowired
    private CheckerService checkerService;

    @Autowired
    protected MemVerificationCache cache;

    @Autowired
    private ClassesService classesService;

    @Autowired
    private SsoCallService ssoCallService;

    @Autowired
    private RelIdService relIdService;

    @Autowired
    private TianBoCheckerService tianBoCheckerService;

    @Autowired
    private ChildrenService childrenService;

    @Autowired
    public void setBaseService(CheckerService service) {
        super.setBaseService(service);
    }


    @ApiOperation(value = "账号 - 添加")
    @PostMapping("/add")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "serialNO", value = "设备序列号", required = false, dataType = "string"),
            @ApiImplicitParam(paramType = "query", name = "address", value = "地域", required = false, dataType = "string"),

    })
    @ApiResponses({
            @ApiResponse(code = 200, message = "OK", response = CheckerPO.class),
    })
    public StatusResponse addChecker(@RequestHeader(TICKET) String ticket, String serialNO, String address) {
        StaffDTO staff = cache.getStaff(ticket);
        Checker checker = checkerService.addChecker(staff.getAreaId(), serialNO, address);
        return StatusResponse.success(checker);
    }


    @RequestMapping(value = "/login", method = RequestMethod.POST)
    @ApiOperation(value = "账号 - 登录")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "checkerId", value = "账号数字", required = true, dataType = "integer"),
            @ApiImplicitParam(paramType = "query", name = "loginPass", value = "密码", required = true, dataType = "string"),
    })
    @ApiResponses({
            @ApiResponse(code = 200, message = "OK", response = CheckerPO.class),
    })
    @ResponseBody
    public StatusResponse login(Integer checkerId, Integer loginPass) {
        Map map = checkerService.login(checkerId, loginPass);
        List<String> ids = new ArrayList<>();
        ids.add(map.get("areaId").toString());
        List<RelId> relIdList = relIdService.findByUserIdIn(ids);
        map.put("areaId", getRelId(relIdList, map.get("areaId").toString()));
        map.put("loginPass", 0);
        return StatusResponse.success(map);
    }


    @ApiOperation(value = "绑卡 - 添加")
    @PostMapping("/add_card")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "userId", value = "用户ID", required = true, dataType = "string"),
            @ApiImplicitParam(paramType = "query", name = "cardNo", value = "卡号", required = true, dataType = "string"),
            @ApiImplicitParam(paramType = "query", name = "type", value = "幼儿1  员工2  家长3", required = true, dataType = "int"),
            @ApiImplicitParam(paramType = "query", name = "relationUserId", value = "宝宝ID，家长卡需要", required = false, dataType = "string"),
    })
    @ApiResponses({
            @ApiResponse(code = 200, message = "OK", response = CheckCardPO.class),
    })
    public StatusResponse addCard(@RequestHeader(TICKET) String ticket, String cardNo, String userId, Integer type, String relationUserId) {
        StaffDTO staff = cache.getStaff(ticket);
        CheckCard card = checkerService.addCard(staff.getAreaId(), cardNo, userId, type, relationUserId);
        return StatusResponse.success(card);
    }


    @ApiOperation(value = "绑卡 - 解绑")
    @PostMapping("/delete_card")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "cardNo", value = "卡号", required = true, dataType = "string"),

    })
    @ApiResponses({
            @ApiResponse(code = 200, message = "OK", response = CheckCardPO.class),
    })
    public StatusResponse deleteCard(String cardNo) {
        checkerService.delete(cardNo);
        return StatusResponse.success("删除成功");
    }

    @ApiOperation(value = "班级 - 列表")
    @PostMapping("/class_list")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "id", value = "园区Int Id", required = true, dataType = "integer"),
    })
    @ApiResponses({
            @ApiResponse(code = 200, message = "OK", response = CheckClassPO.class),
    })
    public StatusResponse classList(Integer id) {
        RelId relId = relIdService.findById(id);
        List<Classes> classList = classesService.getActiveClassesByArea(relId.getUserId());
        List<CheckClassPO> list = new ArrayList<>();

        List<String> ids = classList.stream().map(k -> k.getId()).collect(Collectors.toList());
        List<String> areaIds = classList.stream().map(k -> k.getAreaId()).collect(Collectors.toList());
        ids.addAll(areaIds);
        List<RelId> relIdList = relIdService.findByUserIdIn(ids);
        for (int i = 0; i < classList.size(); i++) {
            CheckClassPO checkClass = new CheckClassPO();
            Classes classes = classList.get(i);
            checkClass.setClassName(classes.getName());
            checkClass.setCapacity(classes.getLimitNum());
            checkClass.setClassInfoID(getRelId(relIdList, classes.getId()));
            checkClass.setKgid(getRelId(relIdList, classes.getAreaId()));
            checkClass.setClassType(classes.getCategory());
            checkClass.setCreateDate(classes.getCreated());
            checkClass.setUpdate(classes.getCreated());
            list.add(checkClass);
        }
        return StatusResponse.success(list);
    }

    @ApiOperation(value = "考勤 - 用户")
    @PostMapping("/getUser")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "id", value = "园区Int Id", required = true, dataType = "int"),
            @ApiImplicitParam(paramType = "query", name = "type", value = "所有0.幼儿1.员工2.家长3", required = true, dataType = "int"),
            @ApiImplicitParam(paramType = "query", name = "whole", value = "1有卡数据，否则所有", required = true, dataType = "int"),
    })
    @ApiResponses({
            @ApiResponse(code = 200, message = "OK", response = CheckUserPO.class),
    })
    public StatusResponse getUser(Integer id, Integer type, Integer whole) {
        RelId relId = relIdService.findById(id);
        List<CheckUserPO> list = checkerService.getUser(relId.getUserId(), type, whole);

        List<String> ids = list.stream().map(k -> k.getClassInfoID()).collect(Collectors.toList());
        List<String> areaIds = list.stream().map(k -> k.getKgId()).collect(Collectors.toList());
        ids.addAll(areaIds);
        List<String> userIds = list.stream().map(k -> k.getUserId()).collect(Collectors.toList());
        ids.addAll(userIds);
        List<RelId> relIdList = relIdService.findByUserIdIn(ids);

        List<CheckUserPOV2>  pov2List = list.stream().map(o -> {
            CheckUserPOV2 checkUserPO = new CheckUserPOV2();
            CopyUtils.copyProperties(o, checkUserPO);
            checkUserPO.setClassInfoID(getRelId(relIdList, o.getClassInfoID()));
            checkUserPO.setKgId(getRelId(relIdList, o.getKgId()));
            checkUserPO.setUserId(getRelId(relIdList, o.getUserId()));
            return checkUserPO;
        }).collect(Collectors.toList());
        return StatusResponse.success(pov2List);
    }


    @ApiOperation(value = "考勤 - 卡")
    @PostMapping("/getCard")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "id", value = "园区Int Id", required = true, dataType = "int"),
            @ApiImplicitParam(paramType = "query", name = "type", value = "所有0.幼儿1.员工2.家长3", required = true, dataType = "int"),
            @ApiImplicitParam(paramType = "query", name = "whole", value = "1有卡数据，否则所有", required = true, dataType = "int"),
    })
    @ApiResponses({
            @ApiResponse(code = 200, message = "OK", response = CheckUserPO.class),
    })
    public StatusResponse getCard(Integer id, Integer type, Integer whole) {
        RelId relId = relIdService.findById(id);
        List<CardPO> list = checkerService.getCard(relId.getUserId(), type, whole);

        List<String> ids = list.stream().map(k -> k.getId()).collect(Collectors.toList());
        List<String> areaIds = list.stream().map(k -> k.getKgId()).collect(Collectors.toList());
        ids.addAll(areaIds);
        List<String> relateIds = list.stream().filter(s -> !StringUtils.equals(s.getRelateId(),"0")).map(k -> k.getRelateId()).collect(Collectors.toList());
        ids.addAll(relateIds);
        List<String> userIds = list.stream().map(k -> k.getUserId()).collect(Collectors.toList());
        ids.addAll(userIds);
        List<RelId> relIdList = relIdService.findByUserIdIn(ids);
        List<CardPOV2>  pov2List = list.stream().map(o -> {
            CardPOV2 cardPOV2 = new CardPOV2();
            CopyUtils.copyProperties(o, cardPOV2);
            cardPOV2.setId(getRelId(relIdList, o.getId()));
            cardPOV2.setKgId(getRelId(relIdList, o.getKgId()));
            cardPOV2.setRelateId(getRelId(relIdList, o.getRelateId()));
            cardPOV2.setUserId(getRelId(relIdList, o.getUserId()));
            cardPOV2.setAccessControlUserId(AccessControlUserIdUtil.GetCardId(o.getCardNo()));
            return cardPOV2;
        }).collect(Collectors.toList());
        return StatusResponse.success(pov2List);
    }


    @ApiOperation(value = "记录 - 添加")
    @PostMapping("/add_record")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "cardNo", value = "卡内码", required = true, dataType = "string"),
            @ApiImplicitParam(paramType = "query", name = "status", value = "状态：1:入园,2:离园", required = true, dataType = "int"),
            @ApiImplicitParam(paramType = "query", name = "checkId", value = "园区Int Id", required = true, dataType = "string"),
            @ApiImplicitParam(paramType = "query", name = "time", value = "考勤时间yyyy-MM-dd HH:mm:ss", required = true, dataType = "string"),
            @ApiImplicitParam(paramType = "query", name = "bitmapStr", value = "base64", required = true, dataType = "string"),
    })
    @ApiResponses({
            @ApiResponse(code = 200, message = "OK", response = CheckCardPO.class),
    })
    public StatusResponse addRecord(String cardNo, int status, String checkId, String time, String bitmapStr,MultipartFile file) {

        String fileName = "photo.jpg";

        MultipartFile fileV1 = Base64ToFile.base64ToMultipartFile(bitmapStr, fileName);

        CheckRecord checkRecord = checkerService.addRecord(cardNo, status, time, checkId, fileV1);

        return StatusResponse.success(checkRecord);
    }


    @ApiOperation(value = "学生 - 卡号信息")
    @PostMapping("/getAllList")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "header", name = "ticket", value = "票据", required = true, dataType = "string"),
            @ApiImplicitParam(paramType = "query", name = "status", value = "状态：1:发卡,2:未发卡", required = true, dataType = "int"),
            @ApiImplicitParam(paramType = "query", name = "classId", value = "班级ID", required = true, dataType = "string"),
    })
    @ApiResponses({
            @ApiResponse(code = 200, message = "OK", response = CheckCardPO.class),
    })
    public StatusResponse getAllList(@RequestHeader(TICKET) String ticket, Integer status, String classId, PagerQuery page) {
        StaffDTO staff = cache.getStaff(ticket);
        Page<UserCardPO> list = checkerService.getAllList(staff.getAreaId(), status, classId, page);
        return StatusResponse.success(list);
    }

    @ApiOperation(value = "家长 - 卡号信息")
    @PostMapping("/getUserCardList")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "header", name = "ticket", value = "票据", required = true, dataType = "string"),
            @ApiImplicitParam(paramType = "query", name = "status", value = "状态：1:发卡,2:未发卡", required = true, dataType = "int"),
            @ApiImplicitParam(paramType = "query", name = "classId", value = "班级ID", required = true, dataType = "string"),
    })
    @ApiResponses({
            @ApiResponse(code = 200, message = "OK", response = CheckCardPO.class),
    })
    public StatusResponse getUserCardList(@RequestHeader(TICKET) String ticket, Integer status, String classId, PagerQuery page) {
        StaffDTO staff = cache.getStaff(ticket);
        Page<UserRelationCardInfoPO> list = checkerService.getUserCardList(staff.getAreaId(), status, classId, page);
        return StatusResponse.success(list);
    }


    @ApiOperation(value = "老师 - 卡号信息")
    @PostMapping("/getStaffCardList")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "header", name = "ticket", value = "票据", required = true, dataType = "string"),
            @ApiImplicitParam(paramType = "query", name = "status", value = "状态：1:发卡,2:未发卡", required = true, dataType = "int"),
            @ApiImplicitParam(paramType = "query", name = "realName", value = "老师名称", required = true, dataType = "string"),
    })
    @ApiResponses({
            @ApiResponse(code = 200, message = "OK", response = CheckCardPO.class),
    })
    public StatusResponse getStaffCardList(@RequestHeader(TICKET) String ticket, String realName, Integer status, PagerQuery pagerQuery) {
        StaffDTO staff = cache.getStaff(ticket);
        //所有有绑卡的园区员工
        List<CheckCard> checkCardList = checkerService.findByTypeAndAreaId(2, staff.getAreaId());
        List<String> userIds = checkCardList.stream().map(k -> k.getUserId()).collect(Collectors.toList());
        String ss = String.join(",", userIds);
        String notStaffIds = null;
        String staffIds = null;
        if (null != status) {
            if (status == 1) {
                staffIds = ss;
            }
            if (status == 2) {
                notStaffIds = ss;
            }
        }
        Map pageMap = ssoCallService.getAreaStaffsV2(ticket, realName, null, 0, notStaffIds, staffIds, pagerQuery);
        List<Map> mapList = (List<Map>) pageMap.get("content");
        List<String> ids = mapList.stream().map(k -> k.get("id").toString()).collect(Collectors.toList());

        for (int i = 0; i < mapList.size(); i++) {
            mapList.get(i).put("cardNo", "");
            mapList.get(i).put("cardCode", "");
            mapList.get(i).put("cardTime", "");
            for (int j = 0; j < checkCardList.size(); j++) {
                if (StringUtils.equals(mapList.get(i).get("id").toString(), checkCardList.get(j).getUserId())) {
                    mapList.get(i).put("cardNo", checkCardList.get(j).getCardNo());
                    mapList.get(i).put("cardCode", checkCardList.get(j).getCardCode());
                    mapList.get(i).put("cardTime", DateUtil.formatDateToStr(checkCardList.get(j).getCreated()));
                }
            }
        }
        PageImpl<Map> userCardPOS = new PageImpl<Map>(mapList, PageRequest.of(Integer.valueOf(pageMap.get("number").toString()), Integer.valueOf(pageMap.get("size").toString())), Integer.valueOf(pageMap.get("totalElements").toString()));
        return StatusResponse.success(userCardPOS);
    }

    @ApiOperation(value = "班级 - 列表V2")
    @PostMapping("/class_list_v2")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "header", name = "ticket", value = "票据", required = true, dataType = "string"),
    })
    @ApiResponses({
            @ApiResponse(code = 200, message = "OK", response = CheckClassPO.class),
    })
    public StatusResponse class_list_v2(@RequestHeader(TICKET) String ticket) {
        StaffDTO staff = cache.getStaff(ticket);

        List<Classes> classList = classesService.getActiveClassesByArea(staff.getAreaId());
        List<String> ids = classList.stream().map(k -> k.getId()).collect(Collectors.toList());
        List<String> areaIds = classList.stream().map(k -> k.getAreaId()).collect(Collectors.toList());
        ids.addAll(areaIds);
        List<RelId> relIdList = relIdService.findByUserIdIn(ids);
        List<CheckClassPO> list = new ArrayList<>();
        for (int i = 0; i < classList.size(); i++) {
            CheckClassPO checkClass = new CheckClassPO();
            Classes classes = classList.get(i);

            checkClass.setClassName(classes.getName());
            checkClass.setCapacity(classes.getLimitNum());
            checkClass.setClassInfoID(getRelId(relIdList, classes.getId()));
            checkClass.setKgid(getRelId(relIdList, classes.getAreaId()));
            checkClass.setClassType(classes.getCategory());
            checkClass.setCreateDate(classes.getCreated());
            checkClass.setUpdate(classes.getCreated());
            list.add(checkClass);
        }
        return StatusResponse.success(list);
    }

    @ApiOperation(value = "卡 - 状态查询")
    @PostMapping("/getCardStatus")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "header", name = "ticket", value = "票据", required = true, dataType = "string"),
            @ApiImplicitParam(paramType = "query", name = "cardNo", value = "卡号", required = true, dataType = "string"),
    })
    @ApiResponses({
            @ApiResponse(code = 200, message = "OK", response = CheckCardPO.class),
    })
    public StatusResponse getCardStatus(@RequestHeader(TICKET) String ticket, String cardNo) {
        StaffDTO staff = cache.getStaff(ticket);
        AreaDTO areaDTO = cache.getArea(ticket);
        CardInfoPO cardInfoPO = checkerService.getCardStatus(staff.getAreaId(), cardNo, ticket);
        if (null != cardInfoPO) {
            cardInfoPO.setAreaInfo(areaDTO.getName());
        }
        return StatusResponse.success(cardInfoPO);
    }

    Integer getRelId(List<RelId> relIdList, String id) {
        if (StringUtils.equals(id,"")){
            return 0;
        }
        for (int i = 0; i < relIdList.size(); i++) {
            if (StringUtils.equals(relIdList.get(i).getUserId(), id)) {
                return relIdList.get(i).getId();
            }
        }
        return 0;
    }

    //锋哥要求
    @ApiOperation(value = "考勤 - 心跳")
    @PostMapping("/deviceOnline")
    public StatusResponse deviceOnline( Integer onlineType,  Integer kgId,  String deviceName,  String appVersion ,String deviceStateInfo) {
        return StatusResponse.success("成功");
    }

    //特性接口
    @ApiOperation(value = "推送全量同步数据")
    @PostMapping("/device/notify_full_sync")
    @ApiResponses({
            @ApiResponse(code = 200, message = "OK", response = CheckerPO.class),
    })
    public StatusResponse notifyFullSync(@RequestHeader(TICKET) String ticket, String checkerId) {

        StaffDTO staff = cache.getStaff(ticket);

        Checker checker = checkerService.getId(checkerId);
        System.out.println("checker======================="+checker);

        if (!checker.getAreaId().equals(staff.getAreaId())){
            return StatusResponse.error(ErrorCode.NON_TARGET, "考勤机不存在");
        }

        if (TianBoCheckerService.TIANBO_MANUFACTURER.equals(checker.getManufacturer())){
            tianBoCheckerService.notifyRemoveAllPerson(staff.getAreaId(), checkerId);

            int pageIndex = 0;
            int pageSize = 10;
            Page<Children> page = childrenService.findTianBoChildrenPage(staff.getAreaId(), PageRequest.of(pageIndex, pageSize));
            System.out.println("Children的数量======================="+page.getSize());
            List<String> ids = page.getContent().stream().map(o -> o.getId()).collect(Collectors.toList());
            tianBoCheckerService.notifySyncPerson(staff.getAreaId(), checkerId, ids);

            while (page.getContent().size() == pageSize){
                //下一页
                pageIndex += 1;

                page = childrenService.findTianBoChildrenPage(staff.getAreaId(), PageRequest.of(pageIndex, pageSize));
                ids = page.getContent().stream().map(o -> o.getId()).collect(Collectors.toList());

                //推送新的一页
                tianBoCheckerService.notifySyncPerson(staff.getAreaId(), checkerId, ids);
            }
        }

        return StatusResponse.success();
    }

    @ApiOperation(value = "推送开门消息")
    @PostMapping("/device/notify_open_door")
    @ApiResponses({
            @ApiResponse(code = 200, message = "OK", response = CheckerPO.class),
    })
    public StatusResponse notifyOpenDoor(@RequestHeader(TICKET) String ticket, String checkerId) {

        StaffDTO staff = cache.getStaff(ticket);

        Checker checker = checkerService.getId(checkerId);

        if (!checker.getAreaId().equals(staff.getAreaId())){
            return StatusResponse.error(ErrorCode.NON_TARGET, "考勤机不存在");
        }

        if (TianBoCheckerService.TIANBO_MANUFACTURER.equals(checker.getManufacturer())){
            tianBoCheckerService.notifyOpenDoor(staff.getAreaId(), checkerId);
        }

        return StatusResponse.success();
    }

}
